স্প্রিং ORM ব্যবহারের সময় ডেটাবেস এবং অ্যাপ্লিকেশনের কার্যক্ষমতা বৃদ্ধি করতে Performance Optimization গুরুত্বপূর্ণ। বড় ডেটাবেস বা জটিল ORM অপারেশনে সঠিক কৌশল প্রয়োগ না করলে সিস্টেমের কার্যক্ষমতা হ্রাস পেতে পারে। নিচে স্প্রিং ORM-এর কার্যক্ষমতা বৃদ্ধির বিভিন্ন কৌশল নিয়ে আলোচনা করা হলো।
Lazy Loading ডেটাবেস থেকে প্রয়োজনীয় ডেটা কেবল তখনই লোড করে যখন এটি ব্যবহৃত হয়। এটি মেমোরি এবং ডেটাবেস ট্র্যাফিক কমায়।
@Entity
public class Employee {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "employee")
private List<Task> tasks;
}
ব্যাখ্যা:
Eager Loading সব সম্পর্কিত ডেটা একবারে ফেচ করে। এটি মেমোরি ব্যবহার বাড়ায়, তাই এটি সীমিত করা উচিত।
@OneToMany(fetch = FetchType.EAGER)
private List<Task> tasks;
ব্যাখ্যা:
Hibernate Batch Size ব্যবহার করে একাধিক ডেটা ফেচ বা ইনসার্ট অপারেশন একত্রে সম্পন্ন করে। এটি ডেটাবেস ট্রিপ হ্রাস করে।
hibernate.jdbc.batch_size=20
hibernate.default_batch_fetch_size=10
ব্যাখ্যা:
স্প্রিং ORM-এর ডিফল্ট পদ্ধতির পরিবর্তে কাস্টম SQL বা JPQL কোয়েরি ব্যবহার করে কার্যক্ষমতা বৃদ্ধি করা যায়।
@Query("SELECT e FROM Employee e WHERE e.department = :department")
List<Employee> findByDepartment(@Param("department") String department);
ব্যাখ্যা:
Hibernate বা Spring ORM ক্যাশিং ব্যবহার করে পুনরায় ডেটাবেস কোয়েরি চালানো এড়ানো যায়।
Hibernate এর Second-Level Cache এবং Query Cache ব্যবহার করুন:
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.cache.use_query_cache=true
ব্যাখ্যা:
জটিল বা স্পেসিফিক ডেটাবেস অপারেশনের জন্য Native SQL ব্যবহার কার্যক্ষমতা বাড়ায়।
@Query(value = "SELECT * FROM employees WHERE salary > :salary", nativeQuery = true)
List<Employee> findEmployeesWithHighSalary(@Param("salary") double salary);
ব্যাখ্যা:
ডেটাবেস ট্রানজেকশনগুলো যথাযথভাবে পরিচালনা করা কার্যক্ষমতা বাড়ায়।
@Transactional(propagation = Propagation.REQUIRED)
public void updateEmployee(Employee employee) {
employeeRepository.save(employee);
}
ব্যাখ্যা:
বড় ডেটাসেটের জন্য Pagination এবং Sorting ব্যবহার করে কার্যক্ষমতা উন্নত করা যায়।
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by("name"));
Page<Employee> employees = employeeRepository.findAll(pageRequest);
ব্যাখ্যা:
Hibernate এ N+1 Select Problem হলো Lazy Loading এর ফলে অতিরিক্ত ডেটাবেস কোয়েরি চালানো।
@Query("SELECT e FROM Employee e JOIN FETCH e.tasks WHERE e.id = :id")
Employee findEmployeeWithTasks(@Param("id") int id);
ব্যাখ্যা:
ডেটাবেস টেবিলের কলামের উপর সঠিক Indexing কার্যক্ষমতা বাড়ায়।
CREATE INDEX idx_employee_department ON employees(department);
ব্যাখ্যা:
ভিন্ন পরিবেশের জন্য (Development, Production) আলাদা Performance Configuration Profile ব্যবহার করা।
# application-prod.properties
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.format_sql=false
spring.jpa.properties.hibernate.use_sql_comments=false
ব্যাখ্যা:
স্প্রিং ORM-এর কার্যক্ষমতা অপ্টিমাইজ করতে Lazy Loading, ক্যাশিং, ব্যাচ প্রসেসিং, এবং কাস্টম কোয়েরি ব্যবহার গুরুত্বপূর্ণ। সঠিক কনফিগারেশন এবং কার্যক্ষমতা বৃদ্ধির কৌশল অনুসরণ করলে ডেটাবেস এবং অ্যাপ্লিকেশনের মধ্যে দ্রুততর ইন্টারঅ্যাকশন নিশ্চিত করা যায়।
Spring ORM ডাটাবেস অ্যাক্সেস সহজ করে এবং ডেভেলপারদের জন্য সুবিধাজনক একটি ফ্রেমওয়ার্ক। তবে বড় এবং জটিল ডেটাবেস ব্যবস্থায় এটি পারফরম্যান্স সমস্যার সম্মুখীন হতে পারে। এসব সমস্যার সমাধানের জন্য নির্দিষ্ট Optimization Techniques প্রয়োগ করা হয়।
Hibernate ব্যবহার করার সময় একাধিক সেকেন্ডারি কুয়েরি তৈরি হয় যা N+1 কুয়েরি সমস্যা সৃষ্টি করে।
Spring ORM এ Lazy Loading ব্যবহার করলে সেশন বন্ধ হওয়ার পর ডেটা অ্যাক্সেস করতে গেলে LazyInitializationException হয়।
ডাটাবেসে অপ্টিমাইজড কুয়েরি তৈরি না হলে এটি ডেটা রিট্রিভের গতি কমিয়ে দেয়।
বড় ডেটাসেট লোড করার সময় ডেটা মেমোরিতে ধরে রাখার কারণে মেমোরি সমস্যা দেখা দেয়।
অপ্রয়োজনীয় ট্রানজ্যাকশন দীর্ঘ সময় ধরে সক্রিয় থাকলে এটি সিস্টেমের পারফরম্যান্সকে নেতিবাচকভাবে প্রভাবিত করে।
@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;
Hibernate এ batch fetching ব্যবহার করে একাধিক এনটিটি বা কালেকশন একসঙ্গে রিট্রিভ করুন।
hibernate.default_batch_fetch_size=10
Hibernate এর Second Level Cache এবং Query Cache ব্যবহার করে ডাটাবেস হিট কমান।
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Entity
public class Product {
// Entity fields
}
ডাটাবেসে সরাসরি অপ্টিমাইজড কুয়েরি ব্যবহার করুন।
@Query("SELECT p FROM Product p WHERE p.price > :price")
List<Product> findProductsByPrice(@Param("price") Double price);
বড় ডেটাসেট রিট্রিভ করার সময় Pagination ব্যবহার করুন।
PageRequest pageRequest = PageRequest.of(page, size, Sort.by("price").descending());
productRepository.findAll(pageRequest);
ডাটাবেস টেবিলে প্রয়োজনীয় কলামে Indexing প্রয়োগ করুন।
CREATE INDEX idx_product_price ON product(price);
Hibernate এ JOIN FETCH বা Entity Graph ব্যবহার করুন।
@Query("SELECT p FROM Product p JOIN FETCH p.orders WHERE p.id = :id")
Product findByIdWithOrders(@Param("id") Long id);
Spring Boot এ ডিফল্ট HikariCP ব্যবহার করে Connection Pooling অপ্টিমাইজ করুন।
spring.datasource.hikari.maximum-pool-size=10
কিছু জটিল অপারেশনের জন্য Native SQL Query ব্যবহার করা আরও কার্যকর।
@Query(value = "SELECT * FROM product WHERE price > ?1", nativeQuery = true)
List<Product> findExpensiveProducts(Double price);
Declarative Transaction Management ব্যবহার করুন এবং অপ্রয়োজনীয় ট্রানজ্যাকশন এড়িয়ে চলুন।
@Transactional
public void updateProduct(Product product) {
productRepository.save(product);
}
Spring এবং Hibernate এর পারফরম্যান্স মনিটরিং এবং টিউনিংয়ের জন্য টুল যেমন Hibernate Statistics, Spring Actuator, বা JProfiler ব্যবহার করুন।
spring.jpa.properties.hibernate.generate_statistics=true
Spring ORM ব্যবহার করার সময় পারফরম্যান্স সমস্যাগুলো চিহ্নিত করা এবং সমাধান করা অত্যন্ত গুরুত্বপূর্ণ। সঠিক Fetching Strategy, Caching, Optimized Query Writing, এবং Transaction Management এর মাধ্যমে এই সমস্যাগুলোর সমাধান সম্ভব। উপযুক্ত টেকনিক প্রয়োগ করলে Spring ORM ব্যবহার করে বড় ডেটাবেস অ্যাপ্লিকেশনেও উচ্চতর পারফরম্যান্স নিশ্চিত করা যায়।
N+1 Select Problem একটি সাধারণ সমস্যা যা Hibernate বা JPA ব্যবহার করার সময় দেখা যায়। এটি সাধারণত তখন ঘটে যখন একটি প্রধান কুইরি ডেটাবেস থেকে ডেটা ফেচ করার পর, সেই ডেটার প্রতিটি রেকর্ডের জন্য একটি পৃথক কুইরি চালানো হয়। এর ফলে অপ্রয়োজনীয় অনেক কুইরি চলে, যা অ্যাপ্লিকেশনের কর্মক্ষমতা (performance) হ্রাস করে।
ধরা যাক, আপনার কাছে দুটি টেবিল আছে:
এগুলোর মধ্যে এক-টু-মেনি (One-to-Many) সম্পর্ক রয়েছে। এখন, যদি আপনি Hibernate বা JPA ব্যবহার করে সকল User এবং তাদের Order লোড করতে চান, তবে সমস্যা নিম্নরূপ হতে পারে:
List<User> users = entityManager.createQuery("FROM User", User.class).getResultList();
for (User user : users) {
System.out.println(user.getOrders());
}
প্রথমে একটি কুইরি চালানো হবে যা সকল User রেকর্ড রিট্রিভ করবে।
SELECT * FROM User;
এরপর প্রতিটি User রেকর্ডের জন্য একটি করে Order কুইরি চালানো হবে। যদি ১০০টি User থাকে, তাহলে ১০১টি কুইরি চালানো হবে।
SELECT * FROM Order WHERE user_id = ?;
এটি N+1 Select Problem।
Hibernate এবং JPA-তে এই সমস্যার সমাধান করতে কিছু পদ্ধতি রয়েছে। নিচে কার্যকর পদ্ধতিগুলো উল্লেখ করা হলো:
Hibernate-এ FetchType.LAZY বা FetchType.EAGER ব্যবহার করে ডেটা লোড করার পদ্ধতি নির্ধারণ করা যায়। N+1 সমস্যা সমাধানে প্রায়ই FetchType.EAGER ব্যবহার করা হয়, তবে এটি সবসময় কার্যকর নয়। এর চেয়ে JOIN FETCH
বা Entity Graph পদ্ধতি বেশি কার্যকর।
JOIN FETCH
ব্যবহারList<User> users = entityManager.createQuery(
"SELECT u FROM User u JOIN FETCH u.orders", User.class
).getResultList();
এখানে JOIN FETCH
ব্যবহার করলে Hibernate একবারেই User এবং তাদের Orders লোড করে, ফলে অতিরিক্ত কুইরি চালানো হয় না।
SELECT u.*, o.*
FROM User u
JOIN Order o ON u.id = o.user_id;
Hibernate-এ Batch Fetching একটি কার্যকর পদ্ধতি, যেখানে Hibernate একাধিক রেকর্ডকে একত্রে ফেচ করে।
Hibernate কনফিগারেশনে নিচের প্রোপার্টি সেট করুন:
hibernate.default_batch_fetch_size=10
Hibernate এই কনফিগারেশন অনুযায়ী ডেটা ফেচ করবে, ফলে প্রতিটি User এর জন্য পৃথক কুইরি চালানোর পরিবর্তে, নির্দিষ্ট সংখ্যক Order একসঙ্গে ফেচ করা হবে।
JPA-র Entity Graph ব্যবহার করে আপনি নির্ধারণ করতে পারেন কোন সম্পর্কিত ডেটা একসঙ্গে ফেচ করা হবে।
@EntityGraph(attributePaths = {"orders"})
@Query("SELECT u FROM User u")
List<User> findAllUsersWithOrders();
এটি Hibernate-কে নির্দেশ দেয় যে orders
সম্পর্কটি একসঙ্গে লোড করতে হবে।
যদি শুধুমাত্র প্রয়োজনীয় ডেটা লোড করতে চান, তবে DTO (Data Transfer Object) ব্যবহার করা একটি ভালো পদ্ধতি।
@Query("SELECT new com.example.dto.UserOrderDTO(u.name, o.productName) " +
"FROM User u JOIN u.orders o")
List<UserOrderDTO> findUserOrders();
এটি শুধুমাত্র প্রয়োজনীয় ডেটা রিট্রিভ করবে এবং একটি UserOrderDTO
অবজেক্টে ম্যাপ করবে।
পদ্ধতি | সুবিধা | সীমাবদ্ধতা |
---|---|---|
JOIN FETCH | দ্রুত এবং কার্যকর | জটিল সম্পর্কের ক্ষেত্রে জটিলতা বাড়তে পারে |
Batch Fetching | কম কুইরি, কর্মক্ষমতা উন্নত | সঠিকভাবে কনফিগার না করলে সমস্যা হতে পারে |
Entity Graph | নির্দিষ্ট সম্পর্ক লোড করা সহজ | নতুন ব্যবহারকারীদের জন্য শেখা কঠিন |
DTO Projection | শুধুমাত্র প্রয়োজনীয় ডেটা ফেচ করা যায় | জটিল কোয়েরির ক্ষেত্রে কোড বেশি হয় |
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
// Getters and Setters
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// Getters and Setters
}
JOIN FETCH
উদাহরণ:List<User> users = entityManager.createQuery(
"SELECT u FROM User u JOIN FETCH u.orders", User.class
).getResultList();
for (User user : users) {
System.out.println(user.getName() + ": " + user.getOrders());
}
@EntityGraph(attributePaths = {"orders"})
@Query("SELECT u FROM User u")
List<User> findAllUsersWithOrders();
N+1 Select Problem কার্যক্ষমতা হ্রাসের একটি বড় কারণ। এটি সমাধানে:
JOIN FETCH
এবং Batch Fetching
ব্যবহার করুন।Spring ORM এবং Hibernate/JPA ডেটাবেস পারফরম্যান্স উন্নত করার জন্য বিভিন্ন Fetch Strategies এবং Caching কৌশল ব্যবহার করে। এর মাধ্যমে, ডেটা এক্সেসের সময় বিলম্ব কমানো যায় এবং ডাটাবেসে অপ্রয়োজনীয় কল এড়ানো যায়।
Hibernate বা JPA এর Fetch Strategy নির্দেশ করে কীভাবে অ্যাসোসিয়েটেড ডেটা (এন্টারিটিস) লোড করা হবে। দুইটি প্রধান Fetch Strategy হল: Lazy Loading এবং Eager Loading।
Lazy Loading হল এমন একটি পদ্ধতি যেখানে অ্যাসোসিয়েটেড ডেটা শুধুমাত্র তখন লোড করা হয়, যখন তা প্রথমবারের মতো অ্যাক্সেস করা হয়। এটি মেমরি ব্যবহারের দিক থেকে কার্যকর এবং দ্রুত প্রাথমিক ডেটা লোড করতে সাহায্য করে।
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
// Getters and Setters
}
এখানে orders
সম্পর্কটি Lazy Loading হিসাবে সেট করা হয়েছে। প্রথমবার User
অ্যাক্সেস করলে orders
লোড হবে না; শুধুমাত্র যখন orders
অ্যাক্সেস করা হবে, তখনই ডেটা লোড হবে।
Eager Loading হল এমন একটি পদ্ধতি যেখানে অ্যাসোসিয়েটেড সমস্ত ডেটা একসাথে লোড করা হয়, যখন মূল Entity লোড করা হয়। এটি ডেটা লোড করার সময় বিলম্ব এড়ায়, তবে এটি অতিরিক্ত মেমরি ব্যবহারের জন্য দায়ী হতে পারে।
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
private List<Order> orders;
// Getters and Setters
}
এখানে orders
সম্পর্কটি Eager Loading হিসাবে সেট করা হয়েছে, যার মানে হল যে User
লোড করার সময় orders
সম্পর্কিত সব ডেটা একসাথে লোড হবে।
প্যারামিটার | Lazy Loading | Eager Loading |
---|---|---|
ডেটা লোডিং পদ্ধতি | প্রয়োজন হলে ডেটা লোড হয়। | সকল সম্পর্কিত ডেটা একসাথে লোড হয়। |
পারফরম্যান্স | প্রথমবারের মতো দ্রুত লোডিং, তবে পরে বিলম্ব হতে পারে। | প্রথমবারের মতো ধীর লোডিং, তবে পরবর্তীতে দ্রুত। |
মেমরি ব্যবহারের প্রভাব | কম মেমরি ব্যবহার, অতিরিক্ত ডেটা লোড এড়ানো হয়। | বেশি মেমরি ব্যবহার হতে পারে। |
ব্যবহার | যখন অ্যাসোসিয়েটেড ডেটা কম প্রয়োজন। | যখন অ্যাসোসিয়েটেড ডেটা সবসময় প্রয়োজন। |
Hibernate বা JPA এ Caching ডেটার অ্যাক্সেসকে দ্রুত করে এবং ডেটাবেসের কল কমায়। Caching ডেটা প্রথমবার লোড হওয়ার পরে সেটি Cache-এ সংরক্ষণ করে, যাতে পরবর্তী অ্যাক্সেসে ডেটাবেসে আবার কল না করতে হয়।
Hibernate দুটি প্রধান ধরনের Cache প্রদান করে:
First-Level Cache হল Hibernate Session এর অন্তর্গত একটি Cache। এটি ডিফল্টভাবে সক্রিয় থাকে এবং সেশন জীবনকালের মধ্যে সমস্ত ডেটা Cache-এ সংরক্ষণ করে। এই Cache শুধুমাত্র একটি সেশনের মধ্যে ডেটা রিট্রাইভ করার জন্য ব্যবহৃত হয় এবং সেশন শেষ হওয়ার পর এটি পরিষ্কার হয়ে যায়।
Session session = sessionFactory.openSession();
Product product1 = session.get(Product.class, 1L); // DB call
Product product2 = session.get(Product.class, 1L); // Cache hit, no DB call
Second-Level Cache একটি শেয়ারড Cache যা বিভিন্ন Hibernate সেশন জুড়ে ডেটা সংরক্ষণ করে। এটি কনফিগারেবল এবং বাইরের Cache Providers (যেমন EHCache, Redis, বা Hazelcast) ব্যবহার করা যেতে পারে।
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.6.15.Final</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.8</version>
</dependency>
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double price;
// Getters and Setters
}
Hibernate/JPA-এর Fetch Strategies এবং Caching ব্যবহার করে ডেটাবেসের পারফরম্যান্স বৃদ্ধি করা সম্ভব। সঠিকভাবে এই কৌশলগুলি নির্বাচন এবং কনফিগার করলে অ্যাপ্লিকেশন দ্রুততর এবং আরও স্কেলযোগ্য হয়, যা ব্যবহারকারীদের জন্য উন্নত ব্যবহারকারীর অভিজ্ঞতা প্রদান করে।
Spring ORM এবং Hibernate ব্যবহার করার সময় পারফরম্যান্স অপটিমাইজেশন গুরুত্বপূর্ণ। ডাটাবেস অ্যাক্সেসের সময় সঠিক কৌশলগুলি ব্যবহার না করলে অ্যাপ্লিকেশন ধীর হতে পারে এবং সার্ভারের ওপর অতিরিক্ত চাপ পড়তে পারে। এই সমস্যা সমাধানে বিভিন্ন পদ্ধতি ব্যবহার করা যায় যা ডাটাবেসের কার্যক্ষমতা বৃদ্ধি এবং সিস্টেমের পরিসর বজায় রাখে।
Lazy Loading হল একটি কৌশল যেখানে সম্পর্কিত ডেটা তখনই লোড হয় যখন তা প্রথমবার অ্যাক্সেস করা হয়। এটি অ্যাপ্লিকেশনের পারফরম্যান্সে বড় ধরনের প্রভাব ফেলতে পারে, বিশেষ করে যখন ডেটা ভলিউম বড় হয়।
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import java.util.List;
@Entity
public class Department {
@Id
private int id;
private String name;
@OneToMany(mappedBy = "department", fetch = jakarta.persistence.FetchType.LAZY)
private List<Employee> employees;
// Getter এবং Setter
}
এখানে, employees
সম্পর্কটি Lazy Loading হিসেবে কনফিগার করা হয়েছে, যার মানে হলো ডিপার্টমেন্ট অ্যাক্সেস করার সময় employees তালিকা তখনই লোড হবে, যখন তা ব্যবহৃত হবে।
যখন সম্পর্কিত ডেটা একসাথে প্রয়োজন হয়, তখন Eager Loading ব্যবহার করা উপকারী হতে পারে। এটি ডেটা লোড করার সময় সম্পর্কিত সব ডেটা একযোগে লোড করে।
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import java.util.List;
@Entity
public class Department {
@Id
private int id;
private String name;
@OneToMany(mappedBy = "department", fetch = jakarta.persistence.FetchType.EAGER)
private List<Employee> employees;
// Getter এবং Setter
}
এখানে, employees
সম্পর্কটি Eager Loading হিসেবে কনফিগার করা হয়েছে, যার মানে হলো যখন ডিপার্টমেন্ট লোড হবে, তখন employees সম্পর্কিত ডেটা একসাথে লোড হবে।
N+1 Query Problem হল একটি সাধারণ পারফরম্যান্স সমস্যা যেখানে একাধিক সম্পর্কিত ডেটা লোড করার সময় একাধিক অতিরিক্ত SQL কুয়েরি তৈরি হয়। এটি কার্যকরভাবে ডাটাবেসের ওপর অতিরিক্ত চাপ ফেলে এবং অ্যাপ্লিকেশনের পারফরম্যান্সকে কমিয়ে দেয়। এই সমস্যাটি সমাধান করতে JOIN FETCH ব্যবহার করা হয়।
import org.hibernate.Hibernate;
import org.hibernate.Session;
public class ProductService {
private Session session;
public ProductService(Session session) {
this.session = session;
}
public void fetchAllDepartments() {
List<Department> departments = session.createQuery("from Department d join fetch d.employees", Department.class).getResultList();
for (Department department : departments) {
Hibernate.initialize(department.getEmployees());
}
}
}
এখানে JOIN FETCH ব্যবহার করে একটিমাত্র কুয়েরি মাধ্যমে employees সম্পর্কিত ডেটা লোড করা হয়েছে, যার ফলে N+1 কুয়েরি সমস্যা থেকে মুক্তি পাওয়া গেছে।
Hibernate বা JPA-তে Batch Fetching ব্যবহার করে একাধিক সম্পর্কিত ডেটা একযোগে একাধিক ডাটাবেস কুয়েরি ব্যবহার করে লোড করা যায়। এটি একটি কার্যকরী কৌশল যেখানে একাধিক লোডিং অপারেশন একত্রে করা হয়, ফলে পারফরম্যান্স বৃদ্ধি পায়।
import org.hibernate.Session;
import org.hibernate.query.Query;
public class ProductService {
private Session session;
public ProductService(Session session) {
this.session = session;
}
public void fetchProducts() {
String hql = "from Product";
Query<Product> query = session.createQuery(hql, Product.class);
query.setFetchSize(50); // Batch fetching size
List<Product> products = query.list();
}
}
এখানে setFetchSize(50) ব্যবহার করে ৫০টি রেকর্ড একসাথে লোড করা হয়েছে, যা ডাটাবেসে কম কুয়েরি পাঠিয়ে পারফরম্যান্স উন্নত করতে সাহায্য করে।
Hibernate বা JPA-তে Second-Level Cache ব্যবহার করে ডাটাবেস থেকে পুনরায় ডেটা রিট্রিভ করার সময় ক্যাশিং এর মাধ্যমে পারফরম্যান্স বাড়ানো যায়। ক্যাশে ব্যবহারের মাধ্যমে ডাটাবেসে অতিরিক্ত কল করা কমানো হয় এবং অ্যাপ্লিকেশন দ্রুতগতিতে কাজ করে।
hibernate.cfg.xml
ফাইলে ক্যাশ সক্রিয় করা:
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
Entity ক্লাসে ক্যাশ যোগ করা:
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {
// ফিল্ড এবং Getter/Setter
}
এখানে, Second-Level Cache সক্রিয় করার মাধ্যমে Product Entity-এর ডেটা ক্যাশে সংরক্ষিত হবে, ফলে পুনরায় রিট্রিভ করার সময় দ্রুত পাওয়া যাবে।
পারফরম্যান্স অপটিমাইজেশন কৌশলগুলি অ্যাপ্লিকেশনটিকে আরও দ্রুত, দক্ষ এবং স্কেলেবল করে তোলে। Spring ORM ব্যবহার করলে এই কৌশলগুলি সহজে প্রয়োগ করা যায়, যার মাধ্যমে ডাটাবেস অ্যাক্সেস আরও কার্যকরী হয়।
Read more